/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package abstractClasses;

import datamodel.EntidadesElegidasDataModel;
import facades.AbstractFacade;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Instance;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import qualifiers.EventoEntidadBorrada;
import qualifiers.EventoEntidadCreada;
import qualifiers.EventoEntidadEditada;
import qualifiers.EventoEntidadElegida;
import qualifiers.EventoEntidadesElegidas;

/**
 *
 * @author damfercer
 * @param <T>
 * @param <F>
 */
public abstract class AbstractListadoEntidades<T,F extends AbstractFacade> {
    @Inject
    private Instance<F> entityFacadeInstance;
    private F facade;
    private T entidadElegida;
    //private T[] entidadesElegidas;
    private List<T> entidadesElegidasList;
    private List<T> listadoEntidades;
    private List<T> entidadesFiltradas;
    @Inject
    @EventoEntidadElegida
    private Event<T> eventoEntidadElegida;
    @Inject
    @EventoEntidadesElegidas
    private Event<EntidadesElegidasDataModel> eventoEntidadesElegidas;
    
    public AbstractListadoEntidades(){
        entidadesElegidasList=new ArrayList<T>();
    }
    
    @PostConstruct
    public void init(){
        this.facade=entityFacadeInstance.get();
        listadoEntidades=facade.findAll();
        if(listadoEntidades==null){
            listadoEntidades=new ArrayList<T>();
        }
        entidadesFiltradas=new ArrayList<T>();
    }
    
    //@Override
    public T[] getEntidadesElegidas() {
        if (null == entidadesElegidasList) {
           return null;
        }
        return (T[]) entidadesElegidasList.toArray();   
    }

    //@Override
    public T getEntidadElegida() {
        return entidadElegida;    
    }

    //@Override
    public List<T> getListadoEntidades() {
        return listadoEntidades;
    }
       
    public void elegirEntidad(){
        if(entidadElegida!=null){
            eventoEntidadElegida.fire(entidadElegida);
        }
        else if(entidadesElegidasList!=null && !entidadesElegidasList.isEmpty()){
            EntidadesElegidasDataModel dataModel=new EntidadesElegidasDataModel();
            dataModel.setEntidadesElegidas(entidadesElegidasList);
            eventoEntidadesElegidas.fire(dataModel);
        }
        else{
            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
            Locale locale=context.getViewRoot().getLocale();
            ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
            String errorNoProductoElegido=rb.getString("ErrorNoProductoElegido");
            FacesMessage msg =new FacesMessage(errorNoProductoElegido,errorNoProductoElegido);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, errorNoProductoElegido, errorNoProductoElegido));
        }
    }
    
    public void onEntidadEditada(@Observes @EventoEntidadEditada T e){
        Collections.replaceAll(listadoEntidades, e, e);
        if(entidadesFiltradas!=null && !entidadesFiltradas.isEmpty()){
           Collections.replaceAll(entidadesFiltradas, e, e);
        }
    }
    
    public void onEntidadCreada(@Observes @EventoEntidadCreada T e){
       if(!listadoEntidades.contains(e)){
           listadoEntidades.add(e);
       }
       if(entidadesFiltradas!=null && !entidadesFiltradas.isEmpty()){
           entidadesFiltradas.add(e);
       }
    }
    
    public void onEntidadBorrada(@Observes @EventoEntidadBorrada T e){
        listadoEntidades.remove(e);
        if(entidadesFiltradas!=null && entidadesFiltradas.contains(e)){
           entidadesFiltradas.remove(e);
        }
    }

    //@Override
    public void setEntidadesElegidas(T[] entidadesElegidas) {
        if (null == entidadesElegidas || entidadesElegidas.length == 0) {
                entidadesElegidasList = null;
            } else {
                entidadesElegidasList = new ArrayList<T>(entidadesElegidas.length);
                for (T entity : entidadesElegidas) {
                    this.entidadesElegidasList.add(entity);
                }
            }
    }

    //@Override
    public void setEntidadElegida(T entidadElegida) {
        this.entidadElegida=entidadElegida;
    }

    //@Override
    public void setListadoEntidades(List<T> listadoEntidades) {
        this.listadoEntidades=listadoEntidades;
    }
    
    public void seleccionarEntidad(){
    }
    
    public void deseleccionarEntidad(){
        this.entidadElegida=null;
    }
    

    /**
     * @return the entidadesElegidasList
     */
    public List<T> getEntidadesElegidasList() {
        return entidadesElegidasList;
    }

    /**
     * @param entidadesElegidasList the entidadesElegidasList to set
     */
    public void setEntidadesElegidasList(List<T> entidadesElegidasList) {
        this.entidadesElegidasList = entidadesElegidasList;
    }

    /**
     * @return the facade
     */
    //@Override
    public F getFacade() {
        return facade;
    }

    /**
     * @param facade the facade to set
     */
    public void setFacade(F facade) {
        this.facade = facade;
    }

    /**
     * @return the entityFacadeInstance
     */
    public Instance<F> getEntityFacadeInstance() {
        return entityFacadeInstance;
    }

    /**
     * @param entityFacadeInstance the entityFacadeInstance to set
     */
    public void setEntityFacadeInstance(Instance<F> entityFacadeInstance) {
        this.entityFacadeInstance = entityFacadeInstance;
    }

    /**
     * @return the entidadesFiltradas
     */
    public List<T> getEntidadesFiltradas() {
        return entidadesFiltradas;
    }

    /**
     * @param entidadesFiltradas the entidadesFiltradas to set
     */
    public void setEntidadesFiltradas(List<T> entidadesFiltradas) {
        this.entidadesFiltradas = entidadesFiltradas;
    }
    
}
